#include "main.h"
#include "digital.h"
#include "tim.h"
#include "stdio.h"
#include "oled.h"
#include "analog.h"
#include "fft.h"
#include "util.h"
#include "reconstruct.h"

#define IR_TIM2_CH1 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_5)
#define IR_TIM5_CH1 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
#define IR_TIM4_CH1 HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_12)
#define FFT_LENGTH 4096
#define ALLOWED_MIN_FREQ 512
#define ALLOWED_MAX_FREQ 51200

uint8_t time_up_flag[3];//上升沿标志位
uint8_t time_dowm_flag[3];//下降沿标志位
uint32_t time_up_num[3];//上升沿计敿
uint32_t time_down_num[3];//下降沿计敿
extern char OLEDBuffer1[16], OLEDBuffer2[16], OLEDBuffer3[16], OLEDBuffer4[16];
extern float fftshift_outputbuf[];
extern float peak_indices[];
extern float fft_delta_f;

float get_freq_of_single_tune(unsigned char tim){
	float freq = 0;
	static uint8_t i = 0;
	extern uint8_t randomNum[];
	if(tim == 2){
		HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//函数用于使能定时器某丿鿚道的输入捕获功胿,并使能相应的中断
		HAL_Delay(randomNum[i]);
		freq = SystemCoreClock/2.0/(htim2.Init.Prescaler+1.0)/time_up_num[0];
	}
	else if(tim == 5){
		HAL_TIM_IC_Start_IT(&htim5,TIM_CHANNEL_1);//函数用于使能定时器某丿鿚道的输入捕获功胿,并使能相应的中断
		HAL_Delay(randomNum[i]);
		freq = SystemCoreClock/2.0/(htim5.Init.Prescaler+1.0)/time_up_num[1];
	}
	else if(tim == 4){
		HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1);//函数用于使能定时器某丿鿚道的输入捕获功胿,并使能相应的中断
		HAL_Delay(randomNum[i]);
		freq = SystemCoreClock/2.0/(htim4.Init.Prescaler+1.0)/time_up_num[2];
	}
	i++;
	HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1);
	HAL_TIM_IC_Stop_IT(&htim5,TIM_CHANNEL_1);
	HAL_TIM_IC_Stop_IT(&htim4,TIM_CHANNEL_1);
	return freq;
}

float get_F_of_2SK(char SK_type){
	float F_Hz = 0;
	if(SK_type == 'A'){
		do F_Hz = get_freq_of_single_tune(2);
		while(F_Hz < ALLOWED_MIN_FREQ || !is_near_thousand(F_Hz) || F_Hz > ALLOWED_MAX_FREQ);
	}
	else if(SK_type == 'F'){
//		do F_Hz = get_freq_of_single_tune(5);
//		while(F_Hz < ALLOWED_MIN_FREQ || !is_near_thousand(F_Hz) || F_Hz > ALLOWED_MAX_FREQ);
//		do {
			wave_capture(2);
			fft();
			find_peak_index(fftshift_outputbuf, peak_indices, FFT_LENGTH/2+1, 0.02);
			for (int i = 0; i < FFT_LENGTH/2+1; i++) peak_indices[i] *= fft_delta_f;
//		} while (peak_indices[0] < ALLOWED_MIN_FREQ || !is_near_thousand(peak_indices[0]) || peak_indices[0] > ALLOWED_MAX_FREQ);
		F_Hz = peak_indices[0];
	}
	else if(SK_type == 'P'){
//		do F_Hz = get_freq_of_single_tune(4);
//		while(F_Hz < ALLOWED_MIN_FREQ || !is_near_thousand(F_Hz) || F_Hz > ALLOWED_MAX_FREQ);
//		do {
			wave_capture(2);
			fft();
			find_peak_index(fftshift_outputbuf, peak_indices, FFT_LENGTH/2+1, 0.02);
			for (int i = 0; i < FFT_LENGTH/2+1; i++) peak_indices[i] *= fft_delta_f;
//		} while (peak_indices[0] < ALLOWED_MIN_FREQ || !is_near_thousand(peak_indices[0]) || peak_indices[0] > ALLOWED_MAX_FREQ);
		F_Hz = peak_indices[0];
	}
	return scale_to_near_thousand(F_Hz);
}

float get_h_of_2FSK(float F_Hz){
	float Rc = F_Hz*2;
	short max_peak_index = 0;
	wave_capture(2);
	fft();
	short peak_count = find_peak_index(fftshift_outputbuf, peak_indices, FFT_LENGTH/2+1, 0.02);
//	for (int i = 0; i < FFT_LENGTH/2+1; i++) peak_indices[i] *= fft_delta_f;
	float max_peak_value = fftshift_outputbuf[(short)peak_indices[0]];
	for(short i = 0; i < peak_count; i++){
		if(fftshift_outputbuf[(short)peak_indices[i]] > max_peak_value){
			max_peak_value = fftshift_outputbuf[(short)peak_indices[i]];
			max_peak_index = i;
		}
	}
	printf("\n%.2f", peak_indices[max_peak_index]);
	if(Rc > 0.1) return peak_indices[max_peak_index]*fft_delta_f/Rc;
	else return 0;
}

void display_2SK(char SK_type){
	float F_Hz = get_F_of_2SK(SK_type), Rc_kbps = F_Hz/500;
	stop_output();
	OLED_Clear();
	OLED_ShowString(12,0,"Extended Part",16);
	switch(SK_type){
		case 'A': {OLED_ShowString(16,2,"Amp Shift Key",16); break;}
		case 'F': {
			OLED_ShowString(8,2,"Freq Shift Key",16);
			sprintf(OLEDBuffer3,"h: %.2f", get_h_of_2FSK(F_Hz));
			OLED_ShowString(36,4,OLEDBuffer3,16);
			break;
		}
		case 'P': {OLED_ShowString(0,2,"Phase Shift Key",16); break;}
		default: break;
	}
	printf("\nRate of 2SK code: %.2fkbps", Rc_kbps);
	sprintf(OLEDBuffer4,"Rc: %.2fkbps", Rc_kbps);
	OLED_ShowString(16,6,OLEDBuffer4,16);
	start_output(F_Hz, 1);
}

char digital_recognize(){
	#define TRIGGER_VOLTAGE 0.9
	short peak_count = 0;
	float Vpp1 = wave_capture(1);
	if(Vpp1 > TRIGGER_VOLTAGE) return 'A';
	wave_capture(2);
	fft();
	peak_count = find_peak_index(fftshift_outputbuf, peak_indices, FFT_LENGTH/2+1, 0.1);
	
			printf("Peak Frequency in Spectrum: ");
			if (peak_count > 0) {
				for (int i = 0; i < peak_count; i++) {
					if (i > 0) printf(", ");
					printf("%.2fHz", 25*peak_indices[i]);
				}
			}
			else printf("None");
			printf("\n");
			
	if(is_peak_value_mono_desc(fftshift_outputbuf, peak_indices, peak_count)) return 'P';
	else return 'F';
}

// 捕获中断回调函数，每次捕获到信号就会进入这个回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM2)
	{
		if(IR_TIM2_CH1&&time_up_flag[0]==0)//第一次上卿
		{
			time_up_flag[0]=1;
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极濧为下降沿捕莿
			__HAL_TIM_SET_COUNTER(&htim2, 0); // 计数清零，从头开始计
		}
		else if(IR_TIM2_CH1==0&&time_dowm_flag[0]==0)//下降
		{
			time_down_num[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1); // 读取捕获计数，这个时间即为上升沿持续的时闿
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); // 改变捕获极濧为上升沿捕莿
			time_dowm_flag[0]=1;
		}
		else if(IR_TIM2_CH1&&time_dowm_flag[0]==1)//第二次之后上卿
		{
			time_up_num[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1); // 读取捕获计数，这个时间即为上升沿持续的时闿
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极濧为下降沿捕莿
			time_dowm_flag[0]=0;
			__HAL_TIM_SET_COUNTER(&htim2, 0); // 计数清零，从头开始计
		}
	}
	else if(htim->Instance == TIM5)
	{
		if(IR_TIM5_CH1&&time_up_flag[1]==0)//第一次上卿
		{
			time_up_flag[1]=1;
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极濧为下降沿捕莿
			__HAL_TIM_SET_COUNTER(&htim5, 0); // 计数清零，从头开始计
		}
		else if(IR_TIM5_CH1==0&&time_dowm_flag[1]==0)//下降
		{
			time_down_num[1] = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1); // 读取捕获计数，这个时间即为上升沿持续的时闿
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); // 改变捕获极濧为上升沿捕莿
			time_dowm_flag[1]=1;
		}
		else if(IR_TIM5_CH1&&time_dowm_flag[1]==1)//第二次之后上卿
		{
			time_up_num[1] = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1); // 读取捕获计数，这个时间即为上升沿持续的时闿
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim5, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极濧为下降沿捕莿
			time_dowm_flag[1]=0;
			__HAL_TIM_SET_COUNTER(&htim5, 0); // 计数清零，从头开始计
		}
	}
	else if(htim->Instance == TIM4)
	{
		if(IR_TIM4_CH1&&time_up_flag[2]==0)//第一次上卿
		{
			time_up_flag[2]=1;
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极濧为下降沿捕莿
			__HAL_TIM_SET_COUNTER(&htim4, 0); // 计数清零，从头开始计
		}
		else if(IR_TIM4_CH1==0&&time_dowm_flag[2]==0)//下降
		{
			time_down_num[2] = HAL_TIM_ReadCapturedValue(&htim4,TIM_CHANNEL_1); // 读取捕获计数，这个时间即为上升沿持续的时闿
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); // 改变捕获极濧为上升沿捕莿
			time_dowm_flag[2]=1;
		}
		else if(IR_TIM4_CH1&&time_dowm_flag[2]==1)//第二次之后上卿
		{
			time_up_num[2] = HAL_TIM_ReadCapturedValue(&htim4,TIM_CHANNEL_1); // 读取捕获计数，这个时间即为上升沿持续的时闿
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极濧为下降沿捕莿
			time_dowm_flag[2]=0;
			__HAL_TIM_SET_COUNTER(&htim4, 0); // 计数清零，从头开始计
		}
	}
}
